#ifndef LOG_HPP
#define LOG_HPP
#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
#include <sstream>
#include <stdexcept>

// 条件编译，区分Windows和Linux平台
#ifdef _WIN32
#include <windows.h> // 用于Windows平台的控制台API
#endif
// 日志级别枚举，仿Python的logging模块
enum class LogLevel {
    DEBUG = 0,
    INFO = 1,
    WARNING = 2,
    LOG_ERROR = 3,  // 避免与windows.h中的ERROR宏冲突
    LOG_CRITICAL = 4   // 避免与windows.h中的CRITICAL宏冲突
};

// 日志记录器类
class Log {
public:
    // 构造函数
    Log(bool ToCommond=true,const std::string& log_file = "") {
        // 设置控制台编码为UTF-8 (仅Windows平台)
        #ifdef _WIN32
        SetConsoleOutputCP(CP_UTF8);
        SetConsoleCP(CP_UTF8);
        #endif
        
        if (!log_file.empty()) {
            log_stream.open(log_file, std::ios::app);
            if (!log_stream.is_open()) {
                throw std::runtime_error("Failed to open log file: " + log_file);
            }
            output_to_file = true;
        }
        output_to_bash = ToCommond;
        set_level(LogLevel::DEBUG); // 默认日志级别为DEBUG
    }

    // 析构函数
    ~Log() {
        if (log_stream.is_open()) {
            log_stream.close();
        }
    }

    // 设置日志级别
    void set_level(LogLevel level) {
        current_level = level;
    }

    // 获取当前日志级别
    LogLevel get_level() const {
        return current_level;
    }

    // 日志记录函数
    // debug函数的第一种重载（无格式化）
    std::string debug(const std::string& module, int line, const std::string& message) {
        std::stringstream ss;
        ss << u8"在模块[" << module << u8"]里（时间[" << get_current_time() << u8"],第[" << line << u8"]行），调试信息:[" << message << u8"]。";
        return log(LogLevel::DEBUG, ss.str());
    }
    
    // debug函数的第二种重载（支持格式化信息）
    template<typename... Args>
    std::string debug(const std::string& module, int line, const std::string& format, Args&&... args) {
        // 计算格式化后字符串的长度
        int length = snprintf(nullptr, 0, format.c_str(), std::forward<Args>(args)...);
        if (length < 0) {
            throw std::runtime_error("Format string error");
        }
        
        // 分配足够的内存
        std::string formatted_message(length + 1, '\0');
        snprintf(&formatted_message[0], formatted_message.size(), format.c_str(), std::forward<Args>(args)...);
        formatted_message.resize(length); // 移除末尾的null字符
        
        // 生成完整的日志消息
        std::stringstream ss;
        ss << u8"在模块[" << module << u8"]里（时间[" << get_current_time() << u8"],第[" << line << u8"]行），调试信息:[" << formatted_message << u8"]。";
        
        return log(LogLevel::DEBUG, ss.str());
    }

    std::string info(const std::string& module, int line, const std::string& message) {
        std::stringstream ss;
        ss << u8"在模块[" << module << u8"]里（时间[" << get_current_time() << u8"],第[" << line << u8"]行），记录信息:[" << message << u8"]。";
        return log(LogLevel::INFO, ss.str());
    }

    // info函数的第二种重载，支持格式化信息
    template<typename... Args>
    std::string info(const std::string& module, int line, const std::string& format, Args&&... args) {
        // 计算格式化后字符串的长度
        int length = snprintf(nullptr, 0, format.c_str(), std::forward<Args>(args)...);
        if (length < 0) {
            throw std::runtime_error("Format string error");
        }
        
        // 分配足够的内存
        std::string formatted_message(length + 1, '\0');
        snprintf(&formatted_message[0], formatted_message.size(), format.c_str(), std::forward<Args>(args)...);
        formatted_message.resize(length); // 移除末尾的null字符
        
        // 生成完整的日志消息
        std::stringstream ss;
        ss << u8"在模块[" << module << u8"]里（时间[" << get_current_time() << u8"],第[" << line << u8"]行），记录信息:[" << formatted_message << u8"]。";
        
        return log(LogLevel::INFO, ss.str());
    }

    // warning函数的第一种重载（无格式化）
    std::string warning(const std::string& module, int line, const std::string& message) {
        std::stringstream ss;
        ss << u8"在模块[" << module << u8"]里（时间[" << get_current_time() << u8"],第[" << line << u8"]行），警告信息:[" << message << u8"]。";
        return log(LogLevel::WARNING, ss.str());
    }
    
    // warning函数的第二种重载（支持格式化信息）
    template<typename... Args>
    std::string warning(const std::string& module, int line, const std::string& format, Args&&... args) {
        // 计算格式化后字符串的长度
        int length = snprintf(nullptr, 0, format.c_str(), std::forward<Args>(args)...);
        if (length < 0) {
            throw std::runtime_error("Format string error");
        }
        
        // 分配足够的内存
        std::string formatted_message(length + 1, '\0');
        snprintf(&formatted_message[0], formatted_message.size(), format.c_str(), std::forward<Args>(args)...);
        formatted_message.resize(length); // 移除末尾的null字符
        
        // 生成完整的日志消息
        std::stringstream ss;
        ss << u8"在模块[" << module << u8"]里（时间[" << get_current_time() << u8"],第[" << line << u8"]行），警告信息:[" << formatted_message << u8"]。";
        
        return log(LogLevel::WARNING, ss.str());
    }

    std::string error(const std::string& module, int line, const std::string& message) {
        std::stringstream ss;
        ss << u8"在模块[" << module << u8"]里（时间[" << get_current_time() << u8"],第[" << line << u8"]行），错误信息:[" << message << u8"]。";
        return log(LogLevel::LOG_ERROR, ss.str());
    }

    // error函数的第二种重载（支持格式化信息）
    template<typename... Args>
    std::string error(const std::string& module, int line, const std::string& format, Args&&... args) {
        // 计算格式化后字符串的长度
        int length = snprintf(nullptr, 0, format.c_str(), std::forward<Args>(args)...);
        if (length < 0) {
            throw std::runtime_error("Format string error");
        }
        
        // 分配足够的内存
        std::string formatted_message(length + 1, '\0');
        snprintf(&formatted_message[0], formatted_message.size(), format.c_str(), std::forward<Args>(args)...);
        formatted_message.resize(length); // 移除末尾的null字符
        
        // 生成完整的日志消息
        std::stringstream ss;
        ss << u8"在模块[" << module << u8"]里（时间[" << get_current_time() << u8"],第[" << line << u8"]行），错误信息:[" << formatted_message << u8"]。";
        
        return log(LogLevel::LOG_ERROR, ss.str());
    }

    std::string critical(const std::string& module, int line, const std::string& message) {
        std::stringstream ss;
        ss << u8"在模块[" << module << u8"]里（时间[" << get_current_time() << u8"],第[" << line << u8"]行），严重错误:[" << message << u8"]。";
        return log(LogLevel::LOG_CRITICAL, ss.str());
    }

    // critical函数的第二种重载（支持格式化信息）
    template<typename... Args>
    std::string critical(const std::string& module, int line, const std::string& format, Args&&... args) {
        // 计算格式化后字符串的长度
        int length = snprintf(nullptr, 0, format.c_str(), std::forward<Args>(args)...);
        if (length < 0) {
            throw std::runtime_error("Format string error");
        }
        
        // 分配足够的内存
        std::string formatted_message(length + 1, '\0');
        snprintf(&formatted_message[0], formatted_message.size(), format.c_str(), std::forward<Args>(args)...);
        formatted_message.resize(length); // 移除末尾的null字符
        
        // 生成完整的日志消息
        std::stringstream ss;
        ss << u8"在模块[" << module << u8"]里（时间[" << get_current_time() << u8"],第[" << line << u8"]行），严重错误:[" << formatted_message << u8"]。";
        
        return log(LogLevel::LOG_CRITICAL, ss.str());
    }

    // 记录异常信息
    void exception(const std::string& message, const std::exception& e) {
        std::stringstream ss;
        ss << message << ": " << e.what();
        log(LogLevel::LOG_ERROR, ss.str());
    }
	void openfile(const std::string& log_file){
		log_stream.open(log_file, std::ios::app);
        if (!log_stream.is_open()) {
            throw std::runtime_error("Failed to open log file: " + log_file);
        }
        output_to_file = true;
	}
	void output_file(const bool& flag=false){
        output_to_file = flag;
	}
	void output_bash(const bool& flag=false){
        output_to_bash = flag;
	}
private:
    LogLevel current_level;
    std::ofstream log_stream;
    bool output_to_file = false;
	bool output_to_bash = true;
    // 获取当前时间字符串
    std::string get_current_time() const {
        time_t now = time(0);
        tm tstruct;
        char buf[80];
        tstruct = *localtime(&now);
        strftime(buf, sizeof(buf), "%Y-%m-%d %X", &tstruct);
        return buf;
    }

    // 获取日志级别字符串
    std::string get_level_string(LogLevel level) const {
        switch (level) {
            case LogLevel::DEBUG:
                return "DEBUG";
            case LogLevel::INFO:
                return "INFO";
            case LogLevel::WARNING:
                return "WARNING";
            case LogLevel::LOG_ERROR:
                return "ERROR";
            case LogLevel::LOG_CRITICAL:
                return "CRITICAL";
            default:
                return "UNKNOWN";
        }
    }

    // 实际的日志记录函数
    std::string log(LogLevel level, const std::string& message) {
        if (level < current_level) {
            return ""; // 低于当前日志级别的消息不记录
        }

        std::string level_str = get_level_string(level);
        std::string log_message;
        
        // 输出到控制台
        if(output_to_bash){
            #ifdef _WIN32
            // Windows平台：使用Windows API设置颜色
            // 保存原始控制台颜色
            HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
            CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
            GetConsoleScreenBufferInfo(hConsole, &consoleInfo);
            WORD originalColor = consoleInfo.wAttributes;
            
            // 启用ANSI转义序列支持
            DWORD mode;
            GetConsoleMode(hConsole, &mode);
            SetConsoleMode(hConsole, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
            
            // 根据日志级别设置颜色和格式
            if (level == LogLevel::WARNING) {
                // 设置为黄色文本
                SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
                log_message = level_str + ": " + message;
                std::cout << log_message << "\n";
            } else if (level == LogLevel::LOG_ERROR) {
                // 设置为红色文本
                SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
                log_message = level_str + ": " + message;
                std::cout << log_message << "\n";
            } else if (level == LogLevel::LOG_CRITICAL) {
                // 设置为红色文本
                SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
                log_message = level_str + ": " + message;
                // 输出日志内容
                std::cout << log_message << "\n";
                // 输出下划线
                std::cout << std::string(log_message.length(), '^') << "\n";
            } else {
                // 默认颜色
                log_message = level_str + ": " + message;
                std::cout << log_message << "\n";
            }
            
            // 恢复原始控制台颜色和模式
            SetConsoleTextAttribute(hConsole, originalColor);
            SetConsoleMode(hConsole, mode);
            #else
            // Linux平台：使用ANSI转义序列设置颜色和格式
            if (level == LogLevel::WARNING) {
                // 设置为黄色文本
                std::cout << "\033[33m" << level_str << ": " << message << "\033[0m" << "\n";
            } else if (level == LogLevel::LOG_ERROR) {
                // 设置为红色文本
                std::cout << "\033[31m" << level_str << ": " << message << "\033[0m" << "\n";
            } else if (level == LogLevel::LOG_CRITICAL) {
                // 设置为红色文本并添加下划线
                std::cout << "\033[31;4m" << level_str << ": " << message << "\033[0m" << "\n";
            } else {
                // 默认颜色
                std::cout << level_str << ": " << message << "\n";
            }
            #endif
        } else {
            // 如果不输出到控制台，直接构造日志消息
            log_message = level_str + ": " + message;
        }
        // 输出到文件
        if (output_to_file && log_stream.is_open()) {
            log_stream << log_message << std::endl;
            log_stream.flush();
        }
        return log_message;
    }
};


// 全局日志实例，方便使用
Log logger;
#endif
